package common.dao.orient;

import com.orientechnologies.orient.core.command.script.OCommandScript;
import com.orientechnologies.orient.core.command.traverse.OTraverse;
import com.orientechnologies.orient.core.db.record.OIdentifiable;
import com.orientechnologies.orient.core.id.ORecordId;
import com.orientechnologies.orient.core.sql.OCommandSQL;
import com.orientechnologies.orient.core.sql.filter.OSQLPredicate;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientEdge;
import com.tinkerpop.blueprints.impls.orient.OrientElementIterable;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;

/**
 * Created by common on 2017/3/17.
 */
public class OrientGraphDao {
    static final Logger logger = LoggerFactory.getLogger(OrientGraphDao.class);



    private OrientGraph graph;


    public OrientGraphDao(){


        this.graph = new OrientGraph("remote:192.168.1.107/yagograph", "admin", "admin");

    }



    public OrientGraph getGraph(){
        return this.graph;
    }







    /*
    http://orientdb.com/docs/last/Graph-Blueprints.html#sql-queries
    Iterable
    http://orientdb.com/javadoc/latest/com/orientechnologies/orient/core/sql/OCommandSQL.html
     */
    public static void test_query_command(OrientGraph graph){

        String sql = "select in() from V where yago_id = '<wordnet_president_110467179>';";
        System.out.println(sql);
        Iterable<Vertex> vertexes = (Iterable<Vertex>) graph.command(
                new OCommandSQL(sql )
        ).execute();

        for (Vertex v : vertexes) {
            System.out.println(v.toString());
            for(String key : v.getPropertyKeys()){
                System.out.println("  " + key);
            }
            System.out.println(v.getProperty("in").toString());
            OrientElementIterable in = v.getProperty("in");
            Iterator it = in.iterator();
            while ( it.hasNext() ){
                Vertex itv = (Vertex)it.next();
                System.out.println( itv.toString() + " " + itv.getProperty("@rid"));
            }
        }

        System.out.println("query finished!");

    }


    /*
    http://orientdb.com/docs/last/Graph-Blueprints.html#sql-batch
    OIdentifiable
     */
    public static void test_query_OIdentifiable(OrientGraph graph){

        String sql = "select in() from V where yago_id = '<wordnet_president_110467179>';";

        Iterable<OIdentifiable> in_node_sets = graph.command(new OCommandScript("sql", sql)).execute();

        for(OIdentifiable in_set: in_node_sets){
            System.out.println( in_set );
        }


    }


    public static void test_query_gremlin(OrientGraph graph){
        System.out.println("\n\nGremlin Query!---------------------");
        Vertex v = graph.getVertex("32:770");
        System.out.println(v);
    }


    public static void test_query_traversal(OrientGraph graph){
        System.out.println("\n\nTraverse Query!---------------------");
        for (OIdentifiable id : new OTraverse()
                .target(new ORecordId("#32:770"))
                .fields("out", "in")
                .limit(10)
                .predicate( new OSQLPredicate("$depth <= 5"))) {

            System.out.println( id);
        }
    }




    public static void test_graphdb(OrientGraph graph){

        // 1) create Vertex Type

        graph.createVertexType("Person");
        graph.createVertexType("Address");
        graph.createEdgeType("lives");
        graph.commit();


        // 2) insert Vertexes
        Vertex vPerson = graph.addVertex("class:Person");
        vPerson.setProperty("firstName", "John");
        vPerson.setProperty("lastName", "Smith");

        Vertex vAddress = graph.addVertex("class:Address");
        vAddress.setProperty("street", "Van Ness Ave.");
        vAddress.setProperty("city", "San Francisco");
        vAddress.setProperty("state", "California");

        // 3) edges
        //OrientEdge eLives = graph.addEdge(null, vPerson, vAddress, "lives");

        OrientEdge eLives = graph.addEdge("class:lives", vPerson, vAddress, null);

        graph.commit();

    }

    public static void test_cleandb(OrientGraph graph){

        /*
        graph.command(
                new OCommandSQL( "Delete FROM V WHERE 1=1")
        ).execute();
        graph.command(
                new OCommandSQL( "Delete FROM E WHERE 1=1")
        ).execute();
        */



        Iterable<Vertex> classes  = (Iterable<Vertex>) graph.command(
                new OCommandSQL("select expand(classes) from metadata:schema")
        ).execute();

        for( Vertex c : classes ) {
            //System.out.println("[Class] " + c.getProperty("NAME"));
            //c.
            String name = c.getProperty("name");
            String superClass = c.getProperty("superClass");
            System.out.println("[class=] " + name + " , [superClass=] " + superClass);
            if( "V".equals(superClass) ){
                graph.command(
                        new OCommandSQL("DELETE VERTEX " + name)
                ).execute();
                graph.command(
                        new OCommandSQL("DROP CLASS " + name)
                ).execute();
            }
            if("E".equals(superClass)){
                graph.command(
                        new OCommandSQL("DELETE EDGE " + name)
                ).execute();
                graph.command(
                        new OCommandSQL("DROP CLASS " + name)
                ).execute();
            }

        }


        System.out.println("after drop class");


        classes  = (Iterable<Vertex>) graph.command(
                new OCommandSQL("select expand(classes) from metadata:schema")
        ).execute();

        for( Vertex c : classes ) {
            //System.out.println("[Class] " + c.getProperty("NAME"));
            String name = c.getProperty("name");
            String superClass = c.getProperty("superClass");
            System.out.println("[class=] " + name + " , [superClass=] " + superClass);
        }







    }


    public static void main(String[] args){

        OrientGraphDao dao = new OrientGraphDao();
        OrientGraph graph = dao.getGraph();


        //logger.debug("connected to orient db");

        //test_cleandb(graph);

        //test_graphdb(graph);

        test_query_command(graph);

        test_query_OIdentifiable(graph);

        test_query_gremlin(graph);

        test_query_traversal(graph);




        System.out.println("\n\nconnected to orient db, exit!\n\n");


    }
}
